/**
 * @file params.hpp
 * @author SDK_TEAM
 * @brief
 * @version 0.1
 * @date 2022-10-26
 *
 * Copyright:
 * © 2018 北京灵汐科技有限公司 版权所有。
 * 注意：以下内容均为北京灵汐科技有限公司原创，未经本公司允许，不得转载，否则将视为侵权；对于不遵守此声明或者其他违法使用以下内容者，本公司依法保留追究权。
 * © 2018 Lynxi Technologies Co., Ltd. All rights reserved.
 * NOTICE: All information contained here is, and remains the property of Lynxi.
 * This file can not be copied or distributed without the permission of Lynxi
 * Technologies Co., Ltd.
 *
 */
#pragma once

#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include "util.hpp"
#include "CLI/CLI11.hpp"

#define MAX_CHANNEL_NUM 32

using namespace std;

bool argUsingJson = false;
static std::string argJsonPath;
static std::string argInputVideo;
static std::string argModelPath; // 模型路径
// static std::string argLabelFile;       // label文件路径
static std::string argPostPluginPath; // 后处理插件库的路径
static std::string argOsdPluginPath;  // osd插件库的路径
static std::uint32_t argChannel = 1;  // 期望在每颗芯片上运行几个通道
static std::vector<int> argChipsVec;  // 期望在哪些芯片上运行
static ShowType argShowType = ShowType::DirectShow;
static int argPrintStats;

bool setChips(const char *str, char delim, std::vector<int> &chipsVec)
{
  std::stringstream sStream(str);
  std::string token;
  chipsVec.clear();
  try
  {
    while (getline(sStream, token, delim))
    {
      chipsVec.emplace_back(stoi(token));
    }
  }
  catch (...)
  {
    std::cout << " ERROR! " << token << " is not number!" << std::endl;
    return false;
  }
  if (ArgsParse::checkChips(chipsVec) == false)
  {
    return false;
  }
  return true;
}

bool argsParser(int argc, char *argv[])
{
  CLI::App app;

  string strIds;
  int showType;

  app.add_option("-i,--input_video", argInputVideo, "input MP4 video file path")->default_val("../data/yolov8_segment_with_video_sample/MOT16-09.mp4");
  app.add_option("-d,--device_id", strIds, "test device number which can be 0~N-1 (N is device count). eg.:0,1,2")->default_val("0");
  app.add_option("-c,--channel_count", argChannel, "channel count")->default_val(1);
  app.add_option("-p,--post_plugin", argPostPluginPath, "yolov8s-seg post process plugin path")->default_val("../common/plugin/postprocess/lib/libYolov8SegmentPostPlugin.so");
  app.add_option("-m,--yolov8s-seg_model", argModelPath, "yolov8s-seg model path")->default_val("../model/yolov8s-seg_b1_h640_w640_c3_iuint8_ofloat32_0000/Net_0");
  app.add_option("-o,--osd_plugin", argOsdPluginPath, "osd plugin path")->default_val("../common/plugin/osd-opencv/lib/libOsdPlugin.so");
  app.add_option("-s,--show_type", showType, "0: show test file directly, 1: save test result to be a file")->default_val(0);
  app.add_option("--print_stats", argPrintStats, "0: print frame rate only, 1: print more info")->default_val(0);
  // app.add_option("-j,--json_config", argJsonPath, "json config path (eg: ../data/yolov8_segment_with_video_sample/yolov8-seg_config.json). If set this param, other params will be ignored");

  CLI11_PARSE(app, argc, argv);

  if (!argJsonPath.empty())
  {
    argUsingJson = true;

    if (!IsFileExist(argJsonPath))
    {
      cout << "error : config file is not exsit." << endl;
      return false;
    }
  }
  else
  {
    argUsingJson = false;
    if (!setChips(strIds.c_str(), ',', argChipsVec))
    {
      cout << "error : device id is not valid." << endl;
      return false;
    }

    if (!IsFileExist(argModelPath))
    {
      cout << "error : yolov8s-seg model is not exsit." << endl;
      return false;
    }

    if (!IsFileExist(argPostPluginPath))
    {
      cout << "error : post plugin is not exsit." << endl;
      return false;
    }

    if (!IsFileExist(argOsdPluginPath))
    {
      cout << "error : osd plugin is not exsit." << endl;
      return false;
    }

    if (showType < DirectShow || showType >= OnlyApu)
    {
      cout << "error : show type is invalid." << endl;
      return false;
    }

    argShowType = (ShowType)showType;

    if (argChannel > MAX_CHANNEL_NUM)
    {
      argChannel = MAX_CHANNEL_NUM;
      cout << "info : channel is not more than " << MAX_CHANNEL_NUM << ", it is set to "
           << MAX_CHANNEL_NUM << endl;
    }
    else if (argChannel < 1)
    {
      argChannel = 1;
      cout << "info : channel is less than 1, it is set to 1" << endl;
    }
  }

  return true;
}
